import java.lang.String;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JTextField;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JList;
import javax.swing.JLabel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.WindowConstants;
import javax.swing.JProgressBar;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.FlowLayout;
import java.awt.Component;
import java.net.Socket;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.Serializable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.FileReader;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyAdapter;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.ListSelectionEvent;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

/*##############################################################################

CLASSE Lecteur
Pour un objet qui lit en permanence ce qui vient du serveur

##############################################################################*/
class Lecteur extends Thread {
	private Client master;
	private BufferedReader entree;
	
	public void run() {
		String ligne;
		Pattern p = Pattern.compile("GUI::");
		Matcher m;
		
		try{
			while (true) {
				ligne = this.entree.readLine();
				if ( ligne!=null ) {
					m = p.matcher(ligne);
					if ( m.find() ) {
						this.master.traiteLigne(m.replaceFirst(""));
					} else {
						this.master.appendLigne(ligne);
					}
				}
			}
		} catch (IOException e) {System.out.println("erreur dans le lecteur:"+e);}
	}
	
	public Lecteur(Client cl) {
		this.master=cl;
		this.entree=cl.getTcpReader();
	}
}

/*##############################################################################

CLASSE MyTableModel
Pour que les cellules de mes tables ne soient pas éditables

##############################################################################*/
class MyTableModel extends DefaultTableModel {

	public MyTableModel(Object[][] data, Object[] columnNames) {
		super(data,columnNames);
	}

  @Override
  public boolean isCellEditable(int rowIndex, int columnIndex) {
    return false;
  }
}

/*##############################################################################

CLASSE PRINCIPALE, Client

##############################################################################*/
public class Client extends JFrame implements ActionListener,ListSelectionListener,TableCellRenderer {
	
/***************************************************************************
Constructeur
***************************************************************************/
	public Client(String addrIp, int portTcp) {
		this.initComponents(); //initialise l'interface graphique
		// initialise les éléments tcp
		try {
			//on récupère la liste des noeuds connus
			this.fillInConnu("./connus.txt");
			//ouverture de connexion
			socketTcp = new Socket(addrIp, portTcp);
			toTcp = new PrintWriter(socketTcp.getOutputStream(),true);
			//on prévient le serveur que l'on est une interface GRAPHIQUE
			toTcp.println("gui\r");
			//initialise le lecteur
			lulu = new Lecteur(this);
			lulu.start();
			//on récupère la liste des fichiers dispos sur le serveur
			toTcp.println("list\r");
		} catch (IOException e) {
			System.out.println("Erreur à l'établissement de la connexion");
		}
	}

/***************************************************************************
Génère un BufferedReader pour le lecteur
***************************************************************************/
	public BufferedReader getTcpReader() {
		try {
			return new BufferedReader(new InputStreamReader(this.socketTcp.getInputStream()));
		} catch (IOException e) {
			System.out.println("Génération de BufferReader impossible");
		}
		return null;
	}
	
/***************************************************************************
Traite une ligne reçue du serveur, celle-ci doit être interprétée
***************************************************************************/
	public void traiteLigne(String ligne){
		//this.areaTrace.append(ligne+"\n");
		Pattern p = Pattern.compile("::");
		String[] tokens = p.split(ligne);
		if ( tokens[0].equals("FILELIST") ) {
			this.fileListProcede(tokens);
		} else if ( tokens[0].equals("SEARCH") ) {
			this.searchProcede(tokens);
		} else if ( tokens[0].equals("REPLY") ) {
			this.replyProcede(tokens);
		} else if ( tokens[0].equals("DISCOVER") ) {
			this.discoverProcede(tokens);
		} else if ( tokens[0].equals("CURE") ) {
			this.cureProcede(tokens);
		} else if ( tokens[0].equals("GET") ) {
			this.getProcede(tokens);
		} else if ( tokens[0].equals("DATA") ) {
			this.dataProcede(tokens);
		}
	}
	
/***************************************************************************
Ajoute une ligne dans le texte area.
Pour l'affichage normal venant du serveur, aucune interprétation n'est faite
***************************************************************************/
	public void appendLigne(String ligne){
		this.areaTrace.append(ligne+"\n");
	}
	
/***************************************************************************
Traite une ligne du serveur concernant la liste des fichiers
dispos sur le serveur
***************************************************************************/
	public void fileListProcede(String[] items){
		if ( items[1].equals("CLEAR") ) {
			while (this.modeleFichier.getRowCount()!=0) this.modeleFichier.removeRow(0);
		} else if ( items[1].equals("FILE") ) {
			this.modeleFichier.addRow(new Object[]{items[2],items[3]});
		}
	}
	
/***************************************************************************
Traite une ligne du serveur concernant la liste des recherches effectuées
***************************************************************************/
	public void searchProcede(String[] items){
		if ( items[1].equals("CLEAR") ) {
			this.modeleRecherche.clear();
		} else if ( items[1].equals("WORD") ) {
			this.modeleRecherche.addElement(items[2]);
		}
	}
	
/***************************************************************************
Traite une ligne du serveur concernant la liste des résultats à une recherche
***************************************************************************/
	public void replyProcede(String[] items){
		if ( items[1].equals("CLEAR") ) {
			while (this.modeleResultat.getRowCount()!=0) this.modeleResultat.removeRow(0);
		} else if ( items[1].equals("FILE") ) {
			this.modeleResultat.addRow(new Object[]{items[2],items[3],items[4]});
		}
	}
	
/***************************************************************************
Traite une ligne du serveur concernant la liste des noeuds présents dans le réseau
***************************************************************************/
	public void discoverProcede(String[] items){
		if ( items[1].equals("CLEAR") ) {
			this.modelePresents.clear();
			this.buttonKick.setEnabled(true);
			this.buttonGraph.setEnabled(true);
		} else if ( items[1].equals("NODE") ) {
			this.modelePresents.addElement(items[2]);
		}
	}
	
/***************************************************************************
Traite une ligne du serveur concernant le bouton CURE
***************************************************************************/
	public void cureProcede(String[] items){
		if ( items[1].equals("ON") ) {
			this.buttonCure.setEnabled(true);
		} else if ( items[1].equals("OFF") ) {
			this.buttonCure.setEnabled(false);
		}
	}
	
/***************************************************************************
Traite une ligne du serveur concernant la liste des GET effectués
***************************************************************************/
	public void getProcede(String[] items){
		if ( items[1].equals("CLEAR") ) {
			while (this.modeleReception.getRowCount()!=0) this.modeleReception.removeRow(0);
		} else if ( items[1].equals("NEW") ) {
			JProgressBar pb = new JProgressBar(0,100);
			pb.setValue(0);
			pb.setStringPainted(true);
			this.modeleReception.addRow(new Object[]{new JLabel(items[2]),new JLabel(items[3]),pb,new JLabel(items[5])});
		} else if ( items[1].equals("UPDATE") ) {
			JProgressBar pb = (JProgressBar)this.modeleReception.getValueAt(Integer.parseInt(items[2]), 2);
			pb.setValue(Integer.parseInt(items[3]));
			this.repaint();
		}
	}
	
/***************************************************************************
Traite une ligne du serveur concernant la liste des fichiers envoyés à
d'autres noeuds
***************************************************************************/
	public void dataProcede(String[] items){
		if ( items[1].equals("CLEAR") ) {
			while (this.modeleEnvoi.getRowCount()!=0) this.modeleEnvoi.removeRow(0);
		} else if ( items[1].equals("FILE") ) {
			this.modeleEnvoi.addRow(new Object[]{items[2],items[3],items[4],items[5],items[6]});
		}
	}
	
/***************************************************************************
Lit les noeuds connus dans un fichier et rempli le tableau correspondant
***************************************************************************/
	private void fillInConnu(String fichier) {
		Pattern p = Pattern.compile("::");
		String[] tokens;
		while (this.modeleConnu.getRowCount()!=0) this.modeleConnu.removeRow(0);
		try{
			BufferedReader br = new BufferedReader(new FileReader(fichier));
			while (br.ready()) {
				tokens = p.split(br.readLine());
				this.modeleConnu.addRow(new Object[]{tokens[1],tokens[0]});
			}
			br.close();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}
	
/***************************************************************************
Ajoute un noeud au fichier des noeuds connus
***************************************************************************/
	private void fillInFichierConnu(String fichier, String ad, String name) {
		Pattern p = Pattern.compile("^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}:\\d{4,5}:\\d{4,5}$");
		Matcher m = p.matcher(ad);
		if (m.matches()) {
			try{
				FileWriter fw = new FileWriter(fichier, true);
				fw.write(ad+"::"+name+"::\n");
				fw.close();
				this.fillInConnu(fichier);
			} catch (Exception e) {
				System.out.println(e.getMessage());
				return;
			}
		}
	}
	
/***************************************************************************
Arrivée d'un évènement
***************************************************************************/
  public void actionPerformed(ActionEvent e) {
    if (e.getSource()==this.buttonCommande) {
    	toTcp.println(this.fieldCommande.getText()+"\r");
			this.fieldCommande.setText("");
    } else if (e.getSource()==this.buttonJoin) {
    	toTcp.println("join "+this.fieldIp.getText()+":"+this.fieldTcp.getText()+":"+this.fieldUdp.getText()+"\r");
			this.fieldIp.setText("");
			this.fieldTcp.setText("");
			this.fieldUdp.setText("");
    } else if (e.getSource()==this.buttonLeave) {
    	toTcp.println("leave\r");
    } else if (e.getSource()==this.buttonHalt) {
    	toTcp.println("halt\r");
    	this.dispose();
    } else if (e.getSource()==this.buttonDiscover) {
    	toTcp.println("discover\r");
    } else if (e.getSource()==this.buttonGraph) {
    	toTcp.println("graph\r");
    } else if (e.getSource()==this.buttonRefresh) {
    	toTcp.println("list\r");
    } else if (e.getSource()==this.buttonRecherche) {
    	if (!this.fieldRecherche.getText().equals("")) {
    		toTcp.println("search "+this.fieldRecherche.getText()+"\r");
				this.fieldRecherche.setText("");
				toTcp.println("list_search\r");
			}
    } else if (e.getSource()==this.buttonRecuperer) {
    	if ( (this.tableResultat.getSelectedRow()!=-1) && (this.listRecherche.getSelectedIndex()!=-1) ) {
    		toTcp.println("get "+this.tableResultat.getSelectedRow()+" "+this.listRecherche.getSelectedIndex()+"\r");
    	}
    } else if (e.getSource()==this.buttonKick) {
    	if (this.listPresents.getSelectedIndex()!=-1) {
    		toTcp.println("kick "+(String)this.modelePresents.getElementAt(this.listPresents.getSelectedIndex())+"\r");
    		toTcp.println("discover\r");
    	}
    } else if (e.getSource()==this.buttonCure) {
    	toTcp.println("cure\r");
    } else if (e.getSource()==this.buttonConnu) {
    	if ((this.fieldIp.getText()!="") && (this.fieldTcp.getText()!="") 
    			&& (this.fieldUdp.getText()!="") && (this.fieldConnu.getText()!="")) {
    		this.fillInFichierConnu("./connus.txt",this.fieldIp.getText()+":"+this.fieldTcp.getText()+":"+this.fieldUdp.getText()
    				,this.fieldConnu.getText());
    	}
    } else if (e.getSource()==this.buttonJoinConnu) {
    	if ( (this.tableConnu.getSelectedRow()!=-1) ) {
    		toTcp.println("join "+(String)this.modeleConnu.getValueAt(this.tableConnu.getSelectedRow(),1)+"\r");
    	}
    }
  }
  
/***************************************************************************
 Arrivée d'un évènement de sélection sur une liste
***************************************************************************/
  public void valueChanged(ListSelectionEvent e) {
  	if (e.getSource()==this.listRecherche) {
    	toTcp.println("list_result "+this.listRecherche.getSelectedIndex()+"\r");
    }
  }
  
/***************************************************************************
appui sur une touche dans le fieldCommande
***************************************************************************/
  private void onKeyReleased(KeyEvent e) {
		if ( e.getKeyCode()==KeyEvent.VK_ENTER  ) {
			if (e.getSource()==this.fieldCommande) {
    		toTcp.println(this.fieldCommande.getText()+"\r");
				this.fieldCommande.setText("");
    	} else if ( (e.getSource()==this.fieldIp) || (e.getSource()==this.fieldTcp) || (e.getSource()==this.fieldUdp) ) {
    		toTcp.println("join "+this.fieldIp.getText()+":"+this.fieldTcp.getText()+":"+this.fieldUdp.getText()+"\r");
				this.fieldIp.setText("");
				this.fieldTcp.setText("");
				this.fieldUdp.setText("");
    	} else if (e.getSource()==this.fieldRecherche) {
    		if (!this.fieldRecherche.getText().equals("")) {
    			toTcp.println("search "+this.fieldRecherche.getText()+"\r");
					this.fieldRecherche.setText("");
					toTcp.println("list_search\r");
				}
    	}
		}
	}

/***************************************************************************
Fonction de l'interface TableCellRenderer
***************************************************************************/
	public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
	
		if ((table==this.tableReception) && (column==2)) {
			return (JProgressBar)value;
		} else {
			return (JLabel)value;
		}	
	}
	
/***************************************************************************
Initialise les composants de la fenetre
***************************************************************************/
	private void initComponents() {
		this.setSize(800,400);
    this.setResizable(true);

		this.tabbedPane = new JTabbedPane();
		
		this.panelReseau = new JPanel();
		this.scrollFichier = new JScrollPane(this.tableFichier);
		this.labelSeConnecter = new JLabel("Se connecter au noeud :");
		this.fieldIp = new JTextField(9);
		this.label2Points = new JLabel(":");
		this.fieldTcp = new JTextField(4);
		this.fieldUdp = new JTextField(4);
		this.fieldConnu = new JTextField(8);
		this.buttonJoin = new JButton("Join");
		this.buttonJoin.addActionListener(this);
		this.buttonLeave = new JButton("Leave");
		this.buttonLeave.addActionListener(this);
		this.buttonHalt = new JButton("Halt");
		this.buttonHalt.addActionListener(this);
		this.buttonConnu = new JButton("Ajouter");
		this.buttonConnu.addActionListener(this);
		this.buttonJoinConnu = new JButton("Join");
		this.buttonJoinConnu.addActionListener(this);
		this.buttonDiscover = new JButton("Discover");
		this.buttonDiscover.addActionListener(this);
		this.buttonGraph = new JButton("Graph");
		this.buttonGraph.addActionListener(this);
		this.buttonCure = new JButton("Cure");
		this.buttonCure.addActionListener(this);
		this.buttonKick = new JButton("Kick");
		this.buttonKick.addActionListener(this);
		this.labelFichiersPresents = new JLabel("Fichiers Presents sur le serveur :");
		this.buttonRefresh = new JButton("Refresh");
		this.buttonRefresh.addActionListener(this);
		this.scrollConnu = new JScrollPane(this.tableConnu);
		this.scrollPresents = new JScrollPane(this.listPresents);
		this.modelePresents = new DefaultListModel();
		this.listPresents = new JList(this.modelePresents);
		this.labelNoeudsConnus = new JLabel("Noeuds connus :");
		this.labelNoeudsPresents = new JLabel("Noeuds presents :");
		
		this.panelRecherche = new JPanel();
		this.fieldRecherche = new JTextField();
		this.buttonRecherche = new JButton("Rechercher");
		this.buttonRecherche.addActionListener(this);
		this.modeleRecherche = new DefaultListModel();
		this.listRecherche = new JList(this.modeleRecherche);
		this.buttonRecuperer = new JButton("Recuperer");
		this.buttonRecuperer.addActionListener(this);
		this.labelRecherche = new JLabel("Terme a rechercher :");
		this.labelResultat = new JLabel("Resultats :");
		
		this.panelEchange = new JPanel();
		this.labelReception = new JLabel("Reception");
		this.labelEnvoi = new JLabel("Envoi");
				
		this.panelTrace = new JPanel();
		this.labelCommande = new JLabel("Commande directe :");
		this.fieldCommande = new JTextField();
		this.buttonCommande = new JButton("Envoyer");
		this.buttonCommande.addActionListener(this);
		this.scrollTrace = new JScrollPane(this.areaTrace);
		this.areaTrace = new JTextArea(10,10);
		this.areaTrace.setEditable(false);
		
		JLabel vide = new JLabel();

		this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

		/************************************************************* OK
		ONGLET RESEAU
		*************************************************************/

		/* espace de join/leave */
		this.fieldIp.addKeyListener(new KeyAdapter() {
      	public void keyReleased(KeyEvent evt) {onKeyReleased(evt);}
      });
    this.fieldTcp.addKeyListener(new KeyAdapter() {
      	public void keyReleased(KeyEvent evt) {onKeyReleased(evt);}
      });
    this.fieldUdp.addKeyListener(new KeyAdapter() {
      	public void keyReleased(KeyEvent evt) {onKeyReleased(evt);}
      });
		
		JPanel connec = new JPanel();
		connec.setLayout(new FlowLayout());
		connec.add(this.labelSeConnecter);
		connec.add(this.fieldIp);
		connec.add(new JLabel(":"));
		connec.add(this.fieldTcp);
		connec.add(this.label2Points);
		connec.add(this.fieldUdp);
		connec.add(this.buttonJoin);
		connec.add(this.buttonLeave);
		connec.add(this.buttonHalt);

		/* Tableau utilise pour afficher les fichiers disponibles sur le serveur */
		this.scrollFichier.setViewportView(this.tableFichier);
		String[] ficColumnNames = {"Nom", "Taille (en bytes)"};
		Object[][] ficData = {{null, null}};
		this.modeleFichier = new MyTableModel(ficData, ficColumnNames);
		this.tableFichier = new JTable(this.modeleFichier);
		this.scrollFichier = new JScrollPane(this.tableFichier);
		this.scrollFichier.setViewportView(this.tableFichier);
		JPanel tableFic = new JPanel();
		tableFic.setLayout(new BorderLayout());
		tableFic.add(this.tableFichier.getTableHeader(), BorderLayout.PAGE_START);
		tableFic.add(this.scrollFichier, BorderLayout.CENTER);
		JPanel coteFic = new JPanel();
		coteFic.setLayout(new BorderLayout(6,6));
		coteFic.add(this.labelFichiersPresents, BorderLayout.NORTH);
		coteFic.add(tableFic, BorderLayout.CENTER);
		coteFic.add(this.buttonRefresh, BorderLayout.SOUTH);
	
		/* Tableau utilise pour afficher les noeuds connus */
		String[] connuColumnNames = {"Nom", "Adresse p2p"};
		Object[][] connuData = {{null, null}};
		this.modeleConnu = new MyTableModel(connuData, connuColumnNames);
		this.tableConnu = new JTable(this.modeleConnu);
		this.scrollConnu = new JScrollPane(this.tableConnu);
		this.scrollConnu.setViewportView(this.tableConnu);
		JPanel tableCo = new JPanel();
		tableCo.setLayout(new BorderLayout());
		tableCo.add(this.tableConnu.getTableHeader(), BorderLayout.PAGE_START);
		tableCo.add(this.scrollConnu, BorderLayout.CENTER);
		
		JPanel hautConnu = new JPanel();
		hautConnu.setLayout(new BorderLayout(2,2));
		hautConnu.add(this.buttonJoinConnu, BorderLayout.NORTH);
		hautConnu.add(new JLabel("Nom:"), BorderLayout.WEST);
		hautConnu.add(this.fieldConnu, BorderLayout.CENTER);
		hautConnu.add(this.buttonConnu, BorderLayout.EAST);
		
		JPanel coteConnu = new JPanel();
		coteConnu.setLayout(new BorderLayout(6,6));
		coteConnu.add(this.labelNoeudsConnus, BorderLayout.NORTH);
		coteConnu.add(hautConnu, BorderLayout.SOUTH);
		coteConnu.add(this.scrollConnu, BorderLayout.CENTER);
		
		this.buttonGraph.setEnabled(false);
		JPanel boutopo = new JPanel();
		boutopo.setLayout(new FlowLayout());
		boutopo.add(this.buttonDiscover);
		boutopo.add(this.buttonGraph);
		
		this.buttonCure.setEnabled(false);
		this.buttonKick.setEnabled(false);
		JPanel boutbonus = new JPanel();
		boutbonus.setLayout(new FlowLayout());
		boutbonus.add(this.buttonCure);
		boutbonus.add(this.buttonKick);
		
		this.listPresents.addListSelectionListener(this); 
		this.scrollPresents = new JScrollPane(this.listPresents);
		this.scrollPresents.setViewportView(this.listPresents);
		JPanel cotePresents = new JPanel();
		cotePresents.setLayout(new BorderLayout(6,6));
		cotePresents.add(boutopo, BorderLayout.NORTH);
		cotePresents.add(this.scrollPresents, BorderLayout.CENTER);
		cotePresents.add(boutbonus, BorderLayout.SOUTH);
		
		JPanel coteRePresents = new JPanel();
		coteRePresents.setLayout(new BorderLayout(6,6));
		coteRePresents.add(this.labelNoeudsPresents, BorderLayout.NORTH);
		coteRePresents.add(cotePresents, BorderLayout.CENTER);

		JPanel tousCote = new JPanel();
		tousCote.setLayout(new GridLayout(1,3,10,10));
		tousCote.add(coteFic);
		tousCote.add(coteConnu);
		tousCote.add(coteRePresents);
		
		this.panelReseau.setLayout(new BorderLayout(20,20));
		this.panelReseau.add(connec, BorderLayout.NORTH);
		this.panelReseau.add(tousCote, BorderLayout.CENTER);
		
		this.tabbedPane.addTab("Reseau p2p", this.panelReseau);
		
		/************************************************************* OK
		ONGLET RECHERCHE
		*************************************************************/
		
		this.fieldRecherche.addKeyListener(new KeyAdapter() {
      	public void keyReleased(KeyEvent evt) {onKeyReleased(evt);}
      });
		
		/* espace pour entrer un mot à rechercher */
		JPanel vaChercher = new JPanel();
		vaChercher.setLayout(new GridLayout(3,1,5,5));
		vaChercher.add(this.labelRecherche);
		vaChercher.add(this.fieldRecherche);
		vaChercher.add(this.buttonRecherche);
		
		/* espace avec le mot-clé et la liste des recherches  faites */
		this.listRecherche.addListSelectionListener(this); 
		this.scrollRecherche = new JScrollPane(this.listRecherche);
		this.scrollRecherche.setViewportView(this.listRecherche);
		JPanel coteRech = new JPanel();
		coteRech.setLayout(new BorderLayout(10,10));
		coteRech.add(vaChercher, BorderLayout.NORTH);
		coteRech.add(this.scrollRecherche, BorderLayout.CENTER);

		/* Tableau utilise pour afficher les résiultats d'une recherche */
		String[] resultColumnNames = {"Nom", "Taille (en bytes)", "Source"};
		Object[][] resultData = {{null, null,null}};
		this.modeleResultat = new MyTableModel(resultData, resultColumnNames);
		this.tableResultat = new JTable(this.modeleResultat);
		this.scrollResultat = new JScrollPane(this.tableResultat);
		this.scrollResultat.setViewportView(tableResultat);
		JPanel tableRes = new JPanel();
		tableRes.setLayout(new BorderLayout());
		tableRes.add(this.tableResultat.getTableHeader(), BorderLayout.PAGE_START);
		tableRes.add(this.scrollResultat, BorderLayout.CENTER);
		JPanel coteRes = new JPanel();
		coteRes.setLayout(new BorderLayout(20,20));
		coteRes.add(this.labelResultat, BorderLayout.NORTH);
		coteRes.add(tableRes, BorderLayout.CENTER);
		coteRes.add(this.buttonRecuperer, BorderLayout.SOUTH);
		
		this.panelRecherche.setLayout(new BorderLayout(20,20));
		this.panelRecherche.add(coteRech, BorderLayout.WEST);
		this.panelRecherche.add(coteRes, BorderLayout.CENTER);

		this.tabbedPane.addTab("Recherches de fichiers", this.panelRecherche);

		/************************************************************* OK
		ONGLET ECHANGES
		*************************************************************/
		
		/* Tableau utilise pour afficher les fichiers en download */
		String[] recepColumnNames = {"Nom", "Taille (en bytes)", "Progression", "Source"};
		Object[][] recepData = {{null, null,null,null}};
		this.modeleReception = new MyTableModel(recepData, recepColumnNames);
		this.tableReception = new JTable(this.modeleReception);
		this.tableReception.setDefaultRenderer(this.tableReception.getColumnClass(3) ,this);
		this.modeleReception.removeRow(0); //je sais, c'est moche...
		this.scrollReception = new JScrollPane(this.tableReception);
		this.scrollReception.setViewportView(tableReception);
		JPanel tableHaut = new JPanel();
		tableHaut.setLayout(new BorderLayout());
		tableHaut.add(this.tableReception.getTableHeader(), BorderLayout.PAGE_START);
		tableHaut.add(this.scrollReception, BorderLayout.CENTER);
		
		JPanel echangeHaut = new JPanel();
		echangeHaut.setLayout(new BorderLayout(10,10));
		echangeHaut.add(this.labelReception, BorderLayout.NORTH);
		echangeHaut.add(tableHaut, BorderLayout.CENTER);

		/* Tableau utilise pour afficher les fichiers en upload */
		String[] envoiColumnNames = {"Nom", "Taille (en bytes)", "Begin offset", "End Offset", "Destination"};
		Object[][] envoiData = {{null,null,null,null,null}};
		this.modeleEnvoi = new MyTableModel(envoiData, envoiColumnNames);
		this.tableEnvoi = new JTable(this.modeleEnvoi);
		this.modeleEnvoi.removeRow(0); //je sais, c'est moche...
		this.scrollEnvoi = new JScrollPane(this.tableEnvoi);
		this.scrollEnvoi.setViewportView(tableEnvoi);
		JPanel tableBas = new JPanel();
		tableBas.setLayout(new BorderLayout());
		tableBas.add(this.tableEnvoi.getTableHeader(), BorderLayout.PAGE_START);
		tableBas.add(this.scrollEnvoi, BorderLayout.CENTER);
		
		JPanel echangeBas = new JPanel();
		echangeBas.setLayout(new BorderLayout(10,10));
		echangeBas.add(this.labelEnvoi, BorderLayout.NORTH);
		echangeBas.add(tableBas, BorderLayout.CENTER);
		
		this.panelEchange.setLayout(new GridLayout(2,1,20,20));
		this.panelEchange.add(echangeHaut);
		this.panelEchange.add(echangeBas);

		this.tabbedPane.addTab("Echanges", panelEchange);

		/************************************************************* OK
		ONGLET TRACES
		*************************************************************/

		this.fieldCommande.addKeyListener(new KeyAdapter() {
      	public void keyReleased(KeyEvent evt) {onKeyReleased(evt);}
      });

		JPanel commandesHaut = new JPanel();
		commandesHaut.setLayout(new BorderLayout());
		commandesHaut.add(this.labelCommande,BorderLayout.WEST);
		commandesHaut.add(this.fieldCommande,BorderLayout.CENTER);
		commandesHaut.add(this.buttonCommande,BorderLayout.EAST);

		this.areaTrace.setColumns(20);
		this.areaTrace.setRows(5);
		this.scrollTrace.setViewportView(areaTrace);
		
		this.panelTrace.setLayout(new BorderLayout(20,20));
		this.panelTrace.add(commandesHaut, BorderLayout.NORTH);
		this.panelTrace.add(scrollTrace, BorderLayout.CENTER);
		
		this.tabbedPane.addTab("Traces", this.panelTrace);
		
		/*************************************************************
		FENETRE TOTALE
		*************************************************************/
		
		this.add(this.tabbedPane);
		this.setVisible(true);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
/***************************************************************************
MAIN
***************************************************************************/
	public static void main(String [] args) {
		Client ui=new Client(args[0], Integer.parseInt(args[1]));
	}
	
	
	
	

/***************************************************************************
Attributs de l'interface
***************************************************************************/
	// Elements de communication en TCP avec le serveur
	private Socket socketTcp;
	private PrintWriter toTcp;
	private Lecteur lulu;


	// Elements de l'interface graphique
	private JPanel panelTrace;
	private JLabel labelCommande;
	private JTextField fieldCommande;
	private JButton buttonCommande;
	private JTextArea areaTrace;
	
	private JPanel panelEchange;
	private JLabel labelEnvoi;
	private JLabel labelReception;
	private MyTableModel modeleEnvoi;
	private JTable tableEnvoi;
	private MyTableModel modeleReception;
	private JTable tableReception;
	
	private JButton buttonJoin;
	private JButton buttonLeave;
	private JButton buttonHalt;
	private JButton buttonConnu;
	private JButton buttonJoinConnu;
	private JButton buttonDiscover;
	private JButton buttonGraph;
	private JButton buttonCure;
	private JButton buttonKick;
	private JButton buttonRecherche;
	private JButton buttonRecuperer;
	private JButton buttonRefresh;
	private JTextField fieldIp;
	private JTextField fieldRecherche;
	private JTextField fieldTcp;
	private JTextField fieldUdp;
	private JTextField fieldConnu;
	private JLabel labelSeConnecter;
	private JLabel label2Points;
	private JLabel labelFichiersPresents;
	private JLabel labelNoeudsConnus;
	private JLabel labelNoeudsPresents;
	private JScrollPane scrollResultat;
	private MyTableModel modeleResultat;
	private JTable tableResultat;
	private JLabel labelRecherche;
	private JLabel labelResultat;
	private JTable tableConnu;
	private MyTableModel modeleConnu;
	private JList listPresents;
	private DefaultListModel modelePresents;
	private JList listRecherche;
	private DefaultListModel modeleRecherche;
	private JPanel panelRecherche;
	private JPanel panelReseau;
	private JScrollPane scrollConnu;
	private JScrollPane scrollPresents;
	private JScrollPane scrollEnvoi;
	private JScrollPane scrollFichier;
	private JScrollPane scrollReception;
	private JScrollPane scrollRecherche;
	private JScrollPane scrollTrace;
	private JTabbedPane tabbedPane;
	private MyTableModel modeleFichier;
	private JTable tableFichier;

	
}